<?php

namespace App\EventListener;

use App\Exception\ApiParamValidationException;
use App\Utils\API\Validation\ApiParamValidation;
use App\Utils\Helper\ApiHelper;
use Doctrine\Common\Annotations\AnnotationReader;
use Symfony\Component\HttpKernel\Event\ControllerEvent;

class ApiParameterListener {

    private $request;
    private $method;
    private $annotationReader;
    private $apiParamValidation;

    public function __construct () {
        $this->annotationReader = new AnnotationReader();
        $this->apiParamValidation = new ApiParamValidation();
    }

    public function onKernelController (ControllerEvent $event): void {
        $this->request = $event->getRequest();
        $this->method = $event->getRequest()->getMethod();

        if (!$event->isMasterRequest()) {
            return;
        }

        $controllers = $event->getController();
        if (!is_array($controllers)) {
            return;
        }

        $this->handleApiParams();
    }

    /**
     * API参数校验
     * @throws \Exception
     */
    private function handleApiParams (): void {
        $params = $this->getRequestParams();
        $errors = [];
        foreach (ApiHelper::getInstance()->getParameters() as $annotation) {
            // require
            if ($annotation->require && !isset($params[$annotation->name])) {
                $errors[$annotation->name][] = '字段为必填项';
                continue;
            }
            // type
            if ($this->method == 'POST' && $annotation->type) {
                if (isset($params[$annotation->name])) {
                    $paramType = gettype($params[$annotation->name]);
                    if ($annotation->type != $paramType) {
                        $errors[$annotation->name][] = '字段类型必须为:'.$annotation->type;
                        continue;
                    }
                }
            }
            // validation
            if ($annotation->validation && isset($params[$annotation->name])) {
                $validationResult = $this->apiParamValidation->do($annotation->name, $annotation->validation, $params[$annotation->name]);
                if ($validationResult) {
                    $fieldErrors = $errors[$annotation->name] ?? [];
                    $errors[$annotation->name] = array_merge($fieldErrors, $validationResult);
                    continue;
                }
            }
        }
        if ($errors) {
            throw new ApiParamValidationException($errors);
        }
    }

    /**
     * 非GET请求时，则默认获取body中提交的json数据
     * @return array|mixed
     */
    private function getRequestParams () {
        $result = [];

        if ($this->method === 'GET') {
            $result = $this->request->query->all();
        } else {
            $result = json_decode($this->request->getContent(), true);
        }
        if (!is_array($result)) {
            $result = [];
        }

        return $result;
    }
}